use tokio::{
  io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
  net::TcpListener,
  sync::broadcast,
};

const LOCAL_SERVER: &str = "127.0.0.1:8888";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
  let listener = TcpListener::bind(LOCAL_SERVER).await?;
  let (tx, _rx) = broadcast::channel(12);

  loop {
    let (mut socket, addr) = listener.accept().await?;

    println!("{} connected", addr);
    let tx = tx.clone();
    let mut rx = tx.subscribe();

    tokio::spawn(async move {
      let (reader, mut writer) = socket.split();
      let mut reader = BufReader::new(reader);
      let mut msg = String::new();

      loop {
        tokio::select! {
          result = reader.read_line(&mut msg) => {
            if result.unwrap() == 0 {
              break;
            }
            println!("{}: {}", addr, msg);

            tx.send((msg.clone(), addr)).unwrap();
            msg.clear();
          }
          result = rx.recv() => {
            let (msg_str, other_address) = result.unwrap();
            if addr != other_address {
              println!("发送 {} 到 {}", &msg_str, other_address);
              writer.write_all(msg_str.as_bytes()).await.unwrap();
            }
          }
        }
      }
    });
  }
}
